;; defining entry and table
;; an entry is like a pair of keylist and valuelist with same length
;; eg. '((k1 k2) (v1 v2))
;; a table is a list of entries
;; eg. '(((k1 k2) (v1 v2)) ((k3) (v3)) ((k4 k5 k6) (v4 v5 v6)))

(load "Base.scm")
(load "Pair.scm")

(define new-entry build)

;; lookup-in-entry: if succeed to find, return the value
;; if fail to find, returns (entry-f name)

(define lookup-in-entry
  (lambda (name entry entry-f) 
    (lookup-in-entry-help name (first entry) (second entry) entry-f)))

(define lookup-in-entry-help
  (lambda (name names values entry-f)
    (cond
      ((null? names) (entry-f name))
      ((eq? name (car names)) (car values))
      (else 
        (lookup-in-entry-help name (cdr names) (cdr values) entry-f)))))

;; extend-table: cons an entry and a table (a list of entries)

(define extend-table cons)

;; lookup-in-table: sequentially lookup in each entry in the table
;; if succeed to find (when looking up in one entry), returns the value 
;; (and ignore the other entries)
;; if fail to find, returns (table-f name)

(define lookup-in-table
  (lambda (name table table-f)
    (cond
      ((null? table) (table-f name))
      (else
        (lookup-in-entry name (car table) 
          (lambda (name) (lookup-in-table name (cdr table) table-f)))))))

;; test

(define entry1 (new-entry '(1 2) '(20 30)))
(define entry2 (new-entry '(2 3 4) '(100 200 300)))
(define table1 (extend-table entry1 (extend-table entry2 '())))

(define test 
  (list
    (lookup-in-entry 1 entry1 id)
    (lookup-in-entry 3 entry1 id)
    (lookup-in-table 2 table1 id)
    (lookup-in-table 4 table1 id)
    (lookup-in-table 5 table1 id))) ;; should be '(20 3 30 300 5)
